//http://java.sun.com/developer/onlineTraining/Security/Fundamentals/magercises/ClassLoader/solution/FileClassLoader.java
package generateAndLoadClasses;


import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CharStream;
import org.antlr.runtime.Lexer;
import org.antlr.runtime.TokenRewriteStream;

import Utils.Proprietati;

public class GrammarClassLoader extends ClassLoader {

    private String root;

    public GrammarClassLoader() {
        root = Proprietati.genJavaOut;
    }

    public GrammarClassLoader(String rootDir) {
        if (rootDir == null) {
            throw new IllegalArgumentException("Null root directory");
        }
        root = rootDir;
    }

    @Override
    protected Class loadClass(String name, boolean resolve)
            throws ClassNotFoundException {

        // Since all support classes of loaded class use same class loader
        // must check subclass cache of classes for things like Object

        Class c = findLoadedClass(name);
        if (c == null) {
            try {
                c = findSystemClass(name);
            } catch (Exception e) {
            }
        }

        if (c == null) {
            // Convert class name argument to filename
            // Convert package names into subdirectories
            String filename = name.replace('.', File.separatorChar) + ".class";
            System.out.println(filename);
            try {
                byte data[] = loadClassData(filename);
                c = defineClass(name, data, 0, data.length);
                if (c == null) {
                    throw new ClassNotFoundException(name);
                }
            } catch (IOException e) {
                throw new ClassNotFoundException("Error reading file: " + filename);
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }

    private byte[] loadClassData(String filename)
            throws IOException {

        // Create a file object relative to directory provided
        System.out.println(root);
        File f = new File(root, filename);

        // Get size of class file
        int size = (int) f.length();

        // Reserve space to read
        byte buff[] = new byte[size];

        // Get stream to read from
        FileInputStream fis = new FileInputStream(f);
        DataInputStream dis = new DataInputStream(fis);

        // Read in data
        dis.readFully(buff);

        // close stream
        dis.close();

        // return data
        return buff;
    }

    public static void main(String[] a) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, IllegalArgumentException, InvocationTargetException {
        GrammarClassLoader gcl = new GrammarClassLoader();
        ANTLRStringStream fs = new ANTLRStringStream("a+b");
        Object lex = gcl.loadClass("grammar.impMLexer").getConstructor(CharStream.class).newInstance(fs);
	//impMLexer lex = new impMLexer(fs);
  //  String theType = "impLexer";
  //  Class<? extends org.antlr.runtime.Lexer> theClass = Class.forName(theType).asSubclass(org.antlr.runtime.Lexer.class);

    
        TokenRewriteStream tokens = new TokenRewriteStream((Lexer)lex);
			
        Constructor<? extends java.lang.Object> []c = gcl.loadClass("grammar.impMParser").getConstructors();
        for (Constructor<? extends java.lang.Object> cc : c){
            System.out.println(cc.getName());
            System.out.println(cc.getTypeParameters());
            System.out.println();
        }
        Object f = gcl.loadClass("grammar.impMParser").getConstructor(org.antlr.runtime.TokenStream.class).newInstance(tokens);
        Method[] ms = f.getClass().getMethods();
        for (Method m : ms) {
            System.out.println(m.getName());
        }
    }
}